home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndhrdw / segar.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  16KB  |  531 lines

  1. /***************************************************************************
  2.  
  3. Sega G-80 Raster game sound code
  4.  
  5. Across these games, there's a mixture of discrete sound circuitry,
  6. speech boards, ADPCM samples, and a TMS3617 music chip.
  7.  
  8. 08-JAN-1999 - MAB:
  9.  - added NEC 7751 support to Monster Bash
  10.  
  11. 05-DEC-1998 - MAB:
  12.  - completely rewrote sound code to use Samples interface.
  13.    (It's based on the Zaxxon sndhrdw code.)
  14.  
  15. TODO:
  16.  - Astro Blaster needs "Attack Rate" modifiers implemented
  17.  - Sample support for 005
  18.  - Melody support for 005
  19.  - Sound for Pig Newton
  20.  - Speech for Astro Blaster
  21.  
  22. - Mike Balfour (mab22@po.cwru.edu)
  23. ***************************************************************************/
  24.  
  25. #include "driver.h"
  26. #include "cpu/i8039/i8039.h"
  27.  
  28. #define TOTAL_SOUNDS 16
  29.  
  30. struct sa
  31. {
  32.     int channel;
  33.     int num;
  34.     int looped;
  35.     int stoppable;
  36.     int restartable;
  37. };
  38.  
  39. /***************************************************************************
  40. Astro Blaster
  41.  
  42. Sound is created through two boards.
  43. The Astro Blaster Sound Board consists solely of sounds created through
  44. discrete circuitry.
  45. The G-80 Speech Synthesis Board consists of an 8035 and a speech synthesizer.
  46. ***************************************************************************/
  47.  
  48. /* Special temporary code for Astro Blaster Speech handling */
  49. #define MAX_SPEECH_QUEUE 10
  50. #define NOT_PLAYING     -1              /* The queue holds the sample # so -1 will indicate no sample */
  51. #define SPEECH_CHANNEL 11           /* Note that Astro Blaster sounds only use tracks 0-10 */
  52.  
  53. static int speechQueue[MAX_SPEECH_QUEUE];
  54. static int speechQueuePtr = 0;
  55. /* End of speech code */
  56.  
  57. const char *astrob_sample_names[] =
  58. {
  59.     "*astrob",
  60.     "invadr1.wav","winvadr1.wav","invadr2.wav","winvadr2.wav",
  61.     "invadr3.wav","winvadr3.wav","invadr4.wav","winvadr4.wav",
  62.     "asteroid.wav","refuel.wav",
  63.  
  64.     "pbullet.wav","ebullet.wav","eexplode.wav","pexplode.wav",
  65.     "deedle.wav","sonar.wav",
  66.  
  67.     "01.wav","02.wav","03.wav","04.wav","05.wav","06.wav","07.wav","08.wav",
  68.     "09.wav","0a.wav","0b.wav","0c.wav","0d.wav","0e.wav","0f.wav","10.wav",
  69.     "11.wav","12.wav","13.wav","14.wav","15.wav","16.wav","17.wav","18.wav",
  70.     "19.wav","1a.wav","1b.wav","1c.wav","1d.wav","1e.wav","1f.wav","20.wav",
  71.     "22.wav","23.wav",
  72.     0
  73. };
  74.  
  75. enum
  76. {
  77.     invadr1 = 0,winvadr1,invadr2,winvadr2,
  78.     invadr3,winvadr3,invadr4,winvadr4,
  79.     asteroid,refuel,
  80.     pbullet,ebullet,eexplode,pexplode,
  81.     deedle,sonar,
  82.     v01,v02,v03,v04,v05,v06,v07,v08,
  83.     v09,v0a,v0b,v0c,v0d,v0e,v0f,v10,
  84.     v11,v12,v13,v14,v15,v16,v17,v18,
  85.     v19,v1a,v1b,v1c,v1d,v1e,v1f,v20,
  86.     v22,v23
  87. };
  88.  
  89. static struct sa astrob_sa[TOTAL_SOUNDS] =
  90. {
  91.     /* Port 0x3E: */
  92.     {  0, invadr1,  1, 1, 1 },      /* Line  0 - Invader 1 */
  93.     {  1, invadr2,  1, 1, 1 },      /* Line  1 - Invader 2 */
  94.     {  2, invadr3,  1, 1, 1 },      /* Line  2 - Invader 3 */
  95.     {  3, invadr4,  1, 1, 1 },      /* Line  3 - Invader 4 */
  96.     {  4, asteroid, 1, 1, 1 },      /* Line  4 - Asteroids */
  97.     { -1 },                                         /* Line  5 - <Mute> */
  98.     {  5, refuel,   0, 1, 0 },      /* Line  6 - Refill */
  99.     { -1 },                                         /* Line  7 - <Warp Modifier> */
  100.  
  101.     /* Port 0x3F: */
  102.     {  6, pbullet,  0, 0, 1 },      /* Line  0 - Laser #1 */
  103.     {  7, ebullet,  0, 0, 1 },      /* Line  1 - Laser #2 */
  104.     {  8, eexplode, 0, 0, 1 },      /* Line  2 - Short Explosion */
  105.     {  8, pexplode, 0, 0, 1 },      /* Line  3 - Long Explosion */
  106.     { -1 },                                         /* Line  4 - <Attack Rate> */
  107.     { -1 },                                         /* Line  5 - <Rate Reset> */
  108.     {  9, deedle,   0, 0, 1 },      /* Line  6 - Bonus */
  109.     { 10, sonar,    0, 0, 1 },      /* Line  7 - Sonar */
  110. };
  111.  
  112. /* Special speech handling code.  Someday this will hopefully be
  113.    replaced with true speech synthesis. */
  114. int astrob_speech_sh_start(const struct MachineSound *msound)
  115. {
  116.    int i;
  117.  
  118.    for (i = 0; i < MAX_SPEECH_QUEUE; i++)
  119.    {
  120.       speechQueue[i] = NOT_PLAYING;
  121.    }
  122.    speechQueuePtr = 0;
  123.  
  124.    return 0;
  125. }
  126.  
  127. void astrob_speech_sh_update (void)
  128. {
  129.     int sound;
  130.  
  131.     if( Machine->samples == 0 )
  132.         return;
  133.  
  134.     if (speechQueue[speechQueuePtr] != NOT_PLAYING)
  135.     {
  136.         sound = speechQueue[speechQueuePtr];
  137.  
  138.         if (!sample_playing(SPEECH_CHANNEL))
  139.         {
  140.             if (Machine->samples->sample[sound])
  141.                 sample_start(SPEECH_CHANNEL, sound, 0);
  142.             speechQueue[speechQueuePtr] = NOT_PLAYING;
  143.             speechQueuePtr = ((speechQueuePtr + 1) % MAX_SPEECH_QUEUE);
  144.         }
  145.     }
  146. }
  147.  
  148.  
  149. static void astrob_queue_speech(int sound)
  150. {
  151.     int newPtr;
  152.  
  153.     /* Queue the new sound */
  154.     newPtr = speechQueuePtr;
  155.     while (speechQueue[newPtr] != NOT_PLAYING)
  156.     {
  157.         newPtr = ((newPtr + 1) % MAX_SPEECH_QUEUE);
  158.         if (newPtr == speechQueuePtr)
  159.         {
  160.              /* The queue has overflowed. Oops. */
  161.             logerror("*** Speech queue overflow!\n");
  162.             return;
  163.         }
  164.     }
  165.     speechQueue[newPtr] = sound;
  166. }
  167.  
  168. WRITE_HANDLER( astrob_speech_port_w )
  169. {
  170.     if( Machine->samples == 0 )
  171.         return;
  172.  
  173.     switch (data)
  174.     {
  175.         case 0x01:      astrob_queue_speech(v01); break;
  176.         case 0x02:      astrob_queue_speech(v02); break;
  177.         case 0x03:      astrob_queue_speech(v03); break;
  178.         case 0x04:      astrob_queue_speech(v04); break;
  179.         case 0x05:      astrob_queue_speech(v05); break;
  180.         case 0x06:      astrob_queue_speech(v06); break;
  181.         case 0x07:      astrob_queue_speech(v07); break;
  182.         case 0x08:      astrob_queue_speech(v08); break;
  183.         case 0x09:      astrob_queue_speech(v09); break;
  184.         case 0x0a:      astrob_queue_speech(v0a); break;
  185.         case 0x0b:      astrob_queue_speech(v0b); break;
  186.         case 0x0c:      astrob_queue_speech(v0c); break;
  187.         case 0x0d:      astrob_queue_speech(v0d); break;
  188.         case 0x0e:      astrob_queue_speech(v0e); break;
  189.         case 0x0f:      astrob_queue_speech(v0f); break;
  190.         case 0x10:      astrob_queue_speech(v10); break;
  191.         case 0x11:      astrob_queue_speech(v11); break;
  192.         case 0x12:      astrob_queue_speech(v12); break;
  193.         case 0x13:      astrob_queue_speech(v13); break;
  194.         case 0x14:      astrob_queue_speech(v14); break;
  195.         case 0x15:      astrob_queue_speech(v15); break;
  196.         case 0x16:      astrob_queue_speech(v16); break;
  197.         case 0x17:      astrob_queue_speech(v17); break;
  198.         case 0x18:      astrob_queue_speech(v18); break;
  199.         case 0x19:      astrob_queue_speech(v19); break;
  200.         case 0x1a:      astrob_queue_speech(v1a); break;
  201.         case 0x1b:      astrob_queue_speech(v1b); break;
  202.         case 0x1c:      astrob_queue_speech(v1c); break;
  203.         case 0x1d:      astrob_queue_speech(v1d); break;
  204.         case 0x1e:      astrob_queue_speech(v1e); break;
  205.         case 0x1f:      astrob_queue_speech(v1f); break;
  206.         case 0x20:      astrob_queue_speech(v20); break;
  207.         case 0x22:      astrob_queue_speech(v22); break;
  208.         case 0x23:      astrob_queue_speech(v23); break;
  209.     }
  210. }
  211.  
  212. WRITE_HANDLER( astrob_audio_ports_w )
  213. {
  214.     int line;
  215.     int noise;
  216.     int warp = 0;
  217.  
  218.     /* First, handle special control lines: */
  219.  
  220.     /* MUTE */
  221.     if ((offset == 0) && (data & 0x20))
  222.     {
  223.         /* Note that this also stops our speech from playing. */
  224.         /* (If our speech ever gets synthesized, this will probably
  225.            need to call some type of speech_mute function) */
  226.         for (noise = 0; noise < TOTAL_SOUNDS; noise++)
  227.             sample_stop(astrob_sa[noise].channel);
  228.         return;
  229.     }
  230.  
  231.     /* WARP */
  232.     if ((offset == 0) && (!(data & 0x80)))
  233.     {
  234.         warp = 1;
  235.     }
  236.  
  237.     /* ATTACK RATE */
  238.     if ((offset == 1) && (!(data & 0x10)))
  239.     {
  240.         /* TODO: this seems to modify the speed of the invader sounds */
  241.     }
  242.  
  243.     /* RATE RESET */
  244.     if ((offset == 1) && (!(data & 0x20)))
  245.     {
  246.         /* TODO: this seems to modify the speed of the invader sounds */
  247.     }
  248.  
  249.     /* Now, play our discrete sounds */
  250.     for (line = 0;line < 8;line++)
  251.     {
  252.         noise = 8 * offset + line;
  253.  
  254.         if (astrob_sa[noise].channel != -1)
  255.         {
  256.             /* trigger sound */
  257.             if ((data & (1 << line)) == 0)
  258.             {
  259.                 /* Special case: If we're on Invaders sounds, modify with warp */
  260.                 if ((astrob_sa[noise].num >= invadr1) &&
  261.                     (astrob_sa[noise].num <= invadr4))
  262.                 {
  263.                     if (astrob_sa[noise].restartable || !sample_playing(astrob_sa[noise].channel))
  264.                         sample_start(astrob_sa[noise].channel, astrob_sa[noise].num + warp, astrob_sa[noise].looped);
  265.                 }
  266.                 /* All other sounds are normal */
  267.                 else
  268.                 {
  269.                     if (astrob_sa[noise].restartable || !sample_playing(astrob_sa[noise].channel))
  270.                         sample_start(astrob_sa[noise].channel, astrob_sa[noise].num, astrob_sa[noise].looped);
  271.                 }
  272.             }
  273.             else
  274.             {
  275.                 if (sample_playing(astrob_sa[noise].channel) && astrob_sa[noise].stoppable)
  276.                     sample_stop(astrob_sa[noise].channel);
  277.             }
  278.         }
  279.     }
  280. }
  281.  
  282. /***************************************************************************
  283. 005
  284.  
  285. The Sound Board seems to consist of the following:
  286. An 8255:
  287.   Port A controls the sounds that use discrete circuitry
  288.     A0 - Large Expl. Sound Trig
  289.     A1 - Small Expl. Sound Trig
  290.     A2 - Drop Sound Bomb Trig
  291.     A3 - Shoot Sound Pistol Trig
  292.     A4 - Missile Sound Trig
  293.     A5 - Helicopter Sound Trig
  294.     A6 - Whistle Sound Trig
  295.     A7 - <unused>
  296.   Port B controls the melody generator (described below)
  297.     B0-B3 - connected to addr lines A7-A10 of the 2716 sound ROM
  298.     B4 - connected to 1CL and 2CL on the LS393, and to RD on an LS293 just before output
  299.     B5-B6 - connected to 1CK on the LS393
  300.     B7 - <unused>
  301.   Port C is apparently unused
  302.  
  303. Melody Generator:
  304.     There's an LS393 counter hooked to addr lines A0-A6 of a 2716 ROM.
  305.     Port B from the 8255 hooks to addr lines A7-A10 of the 2716.
  306.     D0-D4 output from the 2716 into an 6331.
  307.     D5 outputs from the 2716 to a 555 timer.
  308.     D0-D7 on the 6331 output to two LS161s.
  309.     The LS161s output to the LS293 (also connected to 8255 B4).
  310.     The output of this feeds into a 4391, which produces "MELODY" output.
  311. ***************************************************************************/
  312.  
  313. const char *s005_sample_names[] =
  314. {
  315.         0
  316. };
  317.  
  318. /***************************************************************************
  319. Space Odyssey
  320.  
  321. The Sound Board consists solely of sounds created through discrete circuitry.
  322. ***************************************************************************/
  323.  
  324. const char *spaceod_sample_names[] =
  325. {
  326.         "fire.wav", "bomb.wav", "eexplode.wav", "pexplode.wav",
  327.         "warp.wav", "birth.wav", "scoreup.wav", "ssound.wav",
  328.         "accel.wav", "damaged.wav", "erocket.wav",
  329.         0
  330. };
  331.  
  332. enum
  333. {
  334.         sofire = 0,sobomb,soeexplode,sopexplode,
  335.         sowarp,sobirth,soscoreup,sossound,
  336.         soaccel,sodamaged,soerocket
  337. };
  338.  
  339. static struct sa spaceod_sa[TOTAL_SOUNDS] =
  340. {
  341.         /* Port 0x0E: */
  342. //      {  0, sossound,   1, 1, 1 },    /* Line  0 - background noise */
  343.         { -1 },                                                 /* Line  0 - background noise */
  344.         { -1 },                                                 /* Line  1 - unused */
  345.         {  1, soeexplode, 0, 0, 1 },    /* Line  2 - Short Explosion */
  346.         { -1 },                                                 /* Line  3 - unused */
  347.         {  2, soaccel,    0, 0, 1 },    /* Line  4 - Accelerate */
  348.         {  3, soerocket,  0, 0, 1 },    /* Line  5 - Battle Star */
  349.         {  4, sobomb,     0, 0, 1 },    /* Line  6 - D. Bomb */
  350.         {  5, sopexplode, 0, 0, 1 },    /* Line  7 - Long Explosion */
  351.         /* Port 0x0F: */
  352.         {  6, sofire,     0, 0, 1 },    /* Line  0 - Shot */
  353.         {  7, soscoreup,  0, 0, 1 },    /* Line  1 - Bonus Up */
  354.         { -1 },                                                 /* Line  2 - unused */
  355.         {  8, sowarp,     0, 0, 1 },    /* Line  3 - Warp */
  356.         { -1 },                                                 /* Line  4 - unused */
  357.         { -1 },                                                 /* Line  5 - unused */
  358.         {  9, sobirth,    0, 0, 1 },    /* Line  6 - Appearance UFO */
  359.         { 10, sodamaged,  0, 0, 1 },    /* Line  7 - Black Hole */
  360. };
  361.  
  362. WRITE_HANDLER( spaceod_audio_ports_w )
  363. {
  364.         int line;
  365.         int noise;
  366.  
  367.         for (line = 0;line < 8;line++)
  368.         {
  369.                 noise = 8 * offset + line;
  370.  
  371.                 if (spaceod_sa[noise].channel != -1)
  372.                 {
  373.                         /* trigger sound */
  374.                         if ((data & (1 << line)) == 0)
  375.                         {
  376.                                 if (spaceod_sa[noise].restartable || !sample_playing(spaceod_sa[noise].channel))
  377.                                         sample_start(spaceod_sa[noise].channel, spaceod_sa[noise].num, spaceod_sa[noise].looped);
  378.                         }
  379.                         else
  380.                         {
  381.                                 if (sample_playing(spaceod_sa[noise].channel) && spaceod_sa[noise].stoppable)
  382.                                         sample_stop(spaceod_sa[noise].channel);
  383.                         }
  384.                 }
  385.         }
  386. }
  387.  
  388. /***************************************************************************
  389. Monster Bash
  390.  
  391. The Sound Board is a fairly complex mixture of different components.
  392. An 8255A-5 controls the interface to/from the sound board.
  393. Port A connects to a TMS3617 (basic music synthesizer) circuit.
  394. Port B connects to two sounds generated by discrete circuitry.
  395. Port C connects to a NEC7751 (8048 CPU derivative) to control four "samples".
  396. ***************************************************************************/
  397.  
  398. static unsigned int port_8255_c03 = 0;
  399. static unsigned int port_8255_c47 = 0;
  400. static unsigned int port_7751_p27 = 0;
  401. static unsigned int rom_offset = 0;
  402.  
  403. const char *monsterb_sample_names[] =
  404. {
  405.         "zap.wav","jumpdown.wav",
  406.         0
  407. };
  408.  
  409. enum
  410. {
  411.         mbzap = 0,mbjumpdown
  412. };
  413.  
  414.  
  415. /* Monster Bash uses an 8255 to control the sounds, much like Zaxxon */
  416. WRITE_HANDLER( monsterb_audio_8255_w )
  417. {
  418.     /* Port A controls the special TMS3617 music chip */
  419.     if (offset == 0)
  420.     {
  421.         int enable_val;
  422.  
  423.         /* Lower four data lines get decoded into 13 control lines */
  424.         tms36xx_note_w(0, 0, data & 15);
  425.  
  426.         /* Top four data lines address an 82S123 ROM that enables/disables voices */
  427.         enable_val = memory_region(REGION_SOUND2)[(data & 0xF0) >> 4];
  428.         tms3617_enable_w(0, enable_val >> 2);
  429.     }
  430.     /* Port B controls the two discrete sound circuits */
  431.     else if (offset == 1)
  432.     {
  433.         if (!(data & 0x01))
  434.             sample_start(0, mbzap, 0);
  435.  
  436.         if (!(data & 0x02))
  437.             sample_start(1, mbjumpdown, 0);
  438.  
  439.         /* TODO: D7 on Port B might affect TMS3617 output (mute?) */
  440.     }
  441.     /* Port C controls a NEC7751, which is an 8048 CPU with onboard ROM */
  442.     else if (offset == 2)
  443.     {
  444.         // D0-D2 = P24-P26, D3 = INT
  445.         port_8255_c03 = data & 0x0F;
  446.         if ((data & 0x08) == 0)
  447.             cpu_cause_interrupt(1,I8039_EXT_INT);
  448.  
  449.     }
  450.     /* Write to 8255 control port, this should be 0x80 for "simple mode" */
  451.     else
  452.     {
  453.         if (data != 0x80)
  454.             logerror("8255 Control Port Write = %02X\n",data);
  455.     }
  456. }
  457.  
  458. READ_HANDLER( monsterb_audio_8255_r )
  459. {
  460.     // Only PC4 is hooked up
  461.     /* 0x00 = BUSY, 0x10 = NOT BUSY */
  462.     return (port_8255_c47 & 0x10);
  463. }
  464.  
  465. /* read from BUS */
  466. READ_HANDLER( monsterb_sh_rom_r )
  467. {
  468.     unsigned char *sound_rom = memory_region(REGION_SOUND1);
  469.  
  470.     return sound_rom[rom_offset];
  471. }
  472.  
  473. /* read from T1 */
  474. READ_HANDLER( monsterb_sh_t1_r )
  475. {
  476.     // Labelled as "TEST", connected to ground
  477.     return 0;
  478. }
  479.  
  480. /* read from P2 */
  481. READ_HANDLER( monsterb_sh_command_r )
  482. {
  483.     // 8255's PC0-2 connects to 7751's S0-2 (P24-P26 on an 8048)
  484.     return ((port_8255_c03 & 0x07) << 4) | port_7751_p27;
  485. }
  486.  
  487. /* write to P1 */
  488. WRITE_HANDLER( monsterb_sh_dac_w )
  489. {
  490.     DAC_data_w(0,data);
  491. }
  492.  
  493. /* write to P2 */
  494. WRITE_HANDLER( monsterb_sh_busy_w )
  495. {
  496.     // 8255's PC0-2 connects to 7751's S0-2 (P24-P26 on an 8048)
  497.     // 8255's PC4 connects to 7751's BSY OUT (P27 on an 8048)
  498.     port_8255_c03 = (data & 0x70) >> 4;
  499.     port_8255_c47 = (data & 0x80) >> 3;
  500.     port_7751_p27 = data & 0x80;
  501. }
  502.  
  503. /* write to P4 */
  504. WRITE_HANDLER( monsterb_sh_offset_a0_a3_w )
  505. {
  506.     rom_offset = (rom_offset & 0x1FF0) | (data & 0x0F);
  507. }
  508.  
  509. /* write to P5 */
  510. WRITE_HANDLER( monsterb_sh_offset_a4_a7_w )
  511. {
  512.     rom_offset = (rom_offset & 0x1F0F) | ((data & 0x0F) << 4);
  513. }
  514.  
  515. /* write to P6 */
  516. WRITE_HANDLER( monsterb_sh_offset_a8_a11_w )
  517. {
  518.     rom_offset = (rom_offset & 0x10FF) | ((data & 0x0F) << 8);
  519. }
  520.  
  521. /* write to P7 */
  522. WRITE_HANDLER( monsterb_sh_rom_select_w )
  523. {
  524.     rom_offset = (rom_offset & 0x0FFF);
  525.  
  526.     /* D0 = !ROM1 enable, D1 = !ROM2 enable, D2/3 hit empty sockets. */
  527.     if ((data & 0x02) == 0)
  528.         rom_offset |= 0x1000;
  529. }
  530.  
  531.